// vim: ft=glsl noet ts=4 sw=4 sts=0
R"vertex(
#version 330 core
smooth out vec2 uv;
layout(location = 0) in vec2 position;

void main()
{
	gl_Position = vec4(position, 0, 1);
	uv = position*0.5 + 0.5;
}
)vertex"

, /////////////////////////////////////////////////////////////////////////

R"fragment(
#version 330 core
out vec3 color;
smooth in vec2 uv;
uniform sampler2D tex;
uniform vec2 dir;
uniform float time;

const float num_samples = 16.0;
const float radius = 128.0;
const float boost = 1.2;
const float nsamples = min(num_samples, radius+1.0);


// for gaussian function
// - mean    : 0.0
// - variance: 0.5
// * GAUSSIAN_MARGIN is the maximum x given gaussian(x) > 1/256
const float PI = atan(1.0) * 4.0;
const float INVSQRT_PI = inversesqrt(PI);
const float GAUSSIAN_MARGIN = 2.23;
float gaussian(float x)
{
    return INVSQRT_PI * exp(-x*x);
}


// uniform over [0, 1]
float rand(vec2 co)
{
    return fract(abs(sin(dot(co, vec2(12.9898, 78.233)))) * 43758.5453);
}


// uniform over [0, 1]
float uniform_dist(vec2 co, float n)
{
    return rand(co + 0.07 * mod(time / 10.0, 10.0) + 0.11 * n);
}


void main()
{
    float total_weight = 0.0;
    vec3 sample = vec3(0);
	vec2 pixel_size = dir / textureSize(tex, 0);

    for (float i=0.0; i<nsamples; i++) {
		float bias_base = (i + uniform_dist(uv, i)) / nsamples - 0.5;   // [-0.5, 0.5)
		float bias = bias_base * radius;
		float weight = gaussian(bias_base * 2.0 * GAUSSIAN_MARGIN);

        total_weight += weight;
		sample += textureLod(tex, uv + bias*pixel_size, 1).rgb * weight;
    }

    color = sample / total_weight * boost;
}
)fragment"

